home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cc04.arc / UMODEM.C < prev    next >
Encoding:
Text File  |  1986-03-15  |  48.1 KB  |  1,220 lines

  1. /*
  2.  *  UMODEM Version 4.0
  3.  *
  4.  *  UMODEM -- Implements the "CP/M User's Group XMODEM" protocol, 
  5.  *            the TERM II File Transfer Protocol (FTP) Number 1,
  6.  *            and the TERM II File Transfer Protocol Number 4 for
  7.  *            packetized file up/downloading.    
  8.  *
  9.  *    Note: UNIX System-Dependent values are indicated by the string [SD]
  10.  *          in a comment field on the same line as the values.
  11.  *
  12.  *
  13.  *         -- Lauren Weinstein, 6/81
  14.  *         -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
  15.  *         -- Version 2.1 Mods by Richard Conn, 8/2/81
  16.  *              . File Size Included on Send Option
  17.  *         -- Version 2.2 Mods by Richard Conn, 8/2/81
  18.  *              . Log File Generation and Option Incorporated
  19.  *         -- Version 2.3 Mods by Richard Conn, 8/3/81
  20.  *              . TERM II FTP 1 Supported
  21.  *              . Error Log Reports Enhanced
  22.  *              . CAN Function Added to FTP 3
  23.  *              . 'd' Option Added to Delete umodem.log File before starting
  24.  *         -- Version 2.4 Mods by Richard Conn, 8/4/81
  25.  *              . 16K-extent sector number check error corrected
  26.  *              . Count of number of received sectors added
  27.  *         -- Version 2.5 Mods by Richard Conn, 8/5/81
  28.  *              . ARPA Net Flag added
  29.  *              . ARPA Net parameter ('a') added to command line
  30.  *              . ARPA Net BIS, BIE, BOS, BOE added
  31.  *              . ARPA Net FFH escape added
  32.  *         -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
  33.  *              . mods for UNIX V7 (Note: for JHU compilation define
  34.  *                the variable JHU  during 'cc'
  35.  *              . added 'mungmode' flag to protect from inadvertant
  36.  *                overwrite on file receive
  37.  *              . changed timeout handling prior to issuing checksum
  38.  *         -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
  39.  *              . correct minor "ifndef" error in which ifndef had no arg
  40.  *              . restructured "ifdef" references so that other versions
  41.  *                of UNIX than Version 7 and JHU can be easily incorporated;
  42.  *                previous ifdef references were for JHU/not JHU;
  43.  *                to compile under Version 7 or JHU UNIX, the following
  44.  *                command lines are recommended:
  45.  *                      "cc umodem.c -o umodem -DVER7" for Version 7
  46.  *                      "cc -7 umodem.c -o umodem -DJHU" for JHU
  47.  *              . added 'y' file status display option; this option gives
  48.  *                the user an estimate of the size of the target file to
  49.  *                send from the UNIX system in terms of CP/M records (128
  50.  *                bytes) and Kbytes (1024 byte units)
  51.  *              . added '7' option which modifies the transmission protocols
  52.  *                for 7 significant bits rather than 8; modifies both FTP 1
  53.  *                and FTP 3
  54.  *         -- Version 2.8 Mods by Richard Conn, 8/28/81
  55.  *              . corrected system-dependent reference to TIOCSSCR (for
  56.  *                disabling page mode) and created the PAGEMODE flag which
  57.  *                is to be set to TRUE to enable this
  58.  *              . added -4 option which engages TERM II, FTP 4 (new release)
  59.  *         -- Version 2.9 Mods by Richard Conn, 9/1/81
  60.  *              . internal documentation on ARPA Net protocols expanded
  61.  *              . possible operator precedence problem with BITMASK corrected
  62.  *                by redundant parentheses
  63.  *         -- Version 3.0 Mods by Lauren Weinstein, 9/14/81
  64.  *              . fixed bug in PAGEMODE defines (removed PAGEMODE define
  65.  *                line; now should be compiled with "-DPAGEMODE" if
  66.  *                Page Mode is desired)
  67.  *              . included forward declaration of ttyname() to avoid problems
  68.  *                with newer V7 C compilers
  69.  *         -- Version 3.1 Mods by Lauren Weinstein, 4/17/82
  70.  *              . avoids sending extraneous last sector when file EOF
  71.  *                occurs on an exact sector boundary
  72.  *         -- Version 3.2 Mods by Michael M Rubenstein, 5/26/83
  73.  *              . fixed bug in readbyte.  assumed that int's are ordered
  74.  *                from low significance to high
  75.  *              . added LOGDEFAULT define to allow default logging to be
  76.  *                off.  compile with -DLOGDEFAULT=0 to set default to no
  77.  *                logging.
  78.  *         -- Version 3.3 Mod by Ben Goldfarb, 07/02/83
  79.  *              . Corrected problem with above implementation of "LOGDEFAULT".
  80.  *                A bitwise, instead of a logical negation operator was
  81.  *                used to complement LOGFLAG when the '-l' command line
  82.  *                flag was specified.  This can cause LOGFLAG to be true
  83.  *                when it should be false.
  84.  *         -- Version 3.4 Mods by David F. Hinnant, NCECS, 7/15/83
  85.  *              . placed log file in HOME directory in case user doesn't
  86.  *                have write permission in working directory.
  87.  *              . added DELDEFAULT define to allow default purge/no purge
  88.  *                of logfile before starting.  Compile with -DDELDEFAULT=0
  89.  *                to set default to NOT delete the log file before starting.
  90.  *              . check log file for sucessful fopen().
  91.  *              . buffer disk read for sfile().
  92.  *              . turn messages off (standard v7) before starting.
  93.  *         -- Version 3.5 Mods by Richard Conn, 08/27/83
  94.  *              . added equates for compilation under UNIX SYSTEM III
  95.  *                      to compile for SYSTEM III, use -DSYS3 instead of
  96.  *                      -DJHU or -DVER7
  97.  *              . added command mode (-c option) for continuous entry
  98.  *                      of commands
  99.  *          --  Version 4.0 Mods by Mycroft Holmes, 04/17/84
  100.  *                . released constraint on using caps for commands in
  101.  *                        the 'command' mode. 
  102.  *                . added descriptors for local mode, allowing use of
  103.  *                        environmental variable 'MODEM' to specify
  104.  *                        i/o port. now, no more limitation to remote
  105.  *                        usage only.
  106.  *                . added rudamentary terminal program for local mode
  107.  *                        and (ala modem7 series, thankyou
  108.  *                        WC) ^E exits terminal mode.  
  109.  *                . reassigned SIGINT to command() when in local mode, thus
  110.  *                        no die from program, just return to command mode.
  111.  *                . put the conditional (on local mode) display of sector
  112.  *                        counts (so you could see it work).
  113.  *                . made case conversions to lower case conditional on
  114.  *                        being upper case, instead of always.  thus using
  115.  *                        lower case in commands works.  (defined 'mklow')
  116.  *                . put in flag to search for in order to get past all this
  117.  *                        garbage at the start of the file.
  118.  *                . forced exit(0) on 'x' from command mode.
  119.  *EOS
  120.  */
  121.  
  122. #include <stdio.h>
  123. #include <sys/types.h>
  124. #include <sys/stat.h>
  125. #include <ctype.h>
  126. #define mklow(c) (isupper(c) ? tolower(c) : c)
  127.  
  128. #include <sgtty.h>
  129.  
  130. /* log default define */
  131. #ifndef LOGDEFAULT
  132. #define LOGDEFAULT      1
  133. #endif
  134.  
  135. /* Delete logfile define.  Useful on small systems with limited
  136.  * filesystem space and careless users.
  137.  */
  138. #ifndef DELDEFAULT
  139. #define DELDEFAULT      1
  140. #endif
  141.  
  142. #include <signal.h>
  143.  
  144. #define      VERSION    40      /* Version Number */
  145. #define      FALSE      0
  146. #define      TRUE       ~FALSE
  147.  
  148. /*  Compile with "-DPAGEMODE" if Page Mode (TIOCSSCR) is supported on your
  149.  *  UNIX system.  If it is supported, make sure that TIOCSSCR is the
  150.  *  correct name for Page Mode engagement.
  151.  */
  152.  
  153. /*  ASCII Constants  */
  154. #define      SOH        001 
  155. #define      STX        002
  156. #define      ETX        003
  157. #define      EOT        004
  158. #define      ENQ        005
  159. #define      ACK        006
  160. #define      LF         012   /* Unix LF/NL */
  161. #define      CR         015  
  162. #define      NAK        025
  163. #define      SYN        026
  164. #define      CAN        030
  165. #define      ESC        033
  166. #define      CTRLZ      032   /* CP/M EOF for text (usually!) */
  167.  
  168. /*  UMODEM Constants  */
  169. #define      TIMEOUT    -1
  170. #define      ERRORMAX   10    /* maximum errors tolerated */
  171. #define      RETRYMAX   10    /* maximum retries to be made */
  172. #define      BBUFSIZ    128   /* buffer size -- do not change! */
  173.  
  174. /*  [SD] Mode for Created Files  */
  175. #define      CREATMODE  0644  /* mode for created files */
  176.  
  177. /*  ARPA Net Constants  */
  178. /*      The following constants are used to communicate with the ARPA
  179.  *      Net SERVER TELNET and TIP programs.  These constants are defined
  180.  *      as follows:
  181.  *              IAC                     <-- Is A Command; indicates that
  182.  *                                              a command follows
  183.  *              WILL/WONT               <-- Command issued to SERVER TELNET
  184.  *                                              (Host); WILL issues command
  185.  *                                              and WONT issues negative of
  186.  *                                              the command
  187.  *              DO/DONT                 <-- Command issued to TIP; DO issues
  188.  *                                              command and DONT issues
  189.  *                                              negative of the command
  190.  *              TRBIN                   <-- Transmit Binary Command
  191.  *      Examples:
  192.  *              IAC WILL TRBIN  <-- Host is configured to transmit Binary
  193.  *              IAC WONT TRBIN  <-- Host is configured NOT to transmit binary
  194.  *              IAC DO TRBIN    <-- TIP is configured to transmit Binary
  195.  *              IAC DONT TRBIN  <-- TIP is configured NOT to transmit binary
  196.  */
  197. #define      IAC        0377    /* Is A Command */
  198. #define      DO         0375    /* Command to TIP */
  199. #define      DONT       0376    /* Negative of Command to TIP */
  200. #define      WILL       0373    /* Command to SERVER TELNET (Host) */
  201. #define      WONT       0374    /* Negative of Command to SERVER TELNET */
  202. #define      TRBIN      0       /* Transmit Binary Command */
  203.  
  204. struct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  205. struct sgttyb  ttycon, ttycom;
  206.  
  207. struct stat statbuf;    /* for terminal message on/off control */
  208. char *strcat();
  209. FILE *LOGFP, *fopen();
  210. char buff[BBUFSIZ];
  211. int nbchr;  /* number of chars read so far for buffered read */
  212.  
  213. int wason;
  214. int i_port, o_port;
  215. int catch;
  216.  
  217. int pagelen;
  218. char *ttyname();  /* forward declaration for C */
  219.  
  220. char *tty;
  221. char XMITTYPE;
  222. int ARPA, CMNDFLAG, RECVFLAG, SENDFLAG, FTP1, PMSG, DELFLAG, LOGFLAG, MUNGMODE;
  223. int STATDISP, BIT7, BITMASK, NOMUNGMODE;
  224. int delay;
  225. char filename[256];
  226.  
  227. alarmfunc();
  228.  
  229. main(argc, argv)
  230. int argc;
  231. char **argv;
  232. {
  233.         char *getenv();
  234.         char *getlogin();
  235.         char *fname = filename;
  236.         char *logfile;
  237.         int index;
  238.         char flag;
  239.  
  240.         logfile = "umodem.log";  /* Name of LOG File */
  241.         i_port = 0;        /* default input port */
  242.         o_port = 1;        /* default output port */
  243.  
  244.         printf("\nUMODEM Version %d.%d", VERSION/10, VERSION%10);
  245.         printf(" -- UNIX-Based Remote File Transfer Facility\n");
  246.  
  247.         if (argc < 2 || *argv[1] != '-')
  248.         {
  249.                 help(FALSE);
  250.                 exit(-1);
  251.         }
  252.  
  253.         index = 1;  /* set index for loop */
  254.         delay = 3;  /* assume FTP 3 delay */
  255.         PMSG = FALSE;  /* turn off flags */
  256.         FTP1 = FALSE;  /* assume FTP 3 (CP/M UG XMODEM2) */
  257.         RECVFLAG = FALSE;  /* not receive */
  258.         SENDFLAG = FALSE;  /* not send either */
  259.         CMNDFLAG = FALSE;  /* not command either */
  260.         XMITTYPE = 't';  /* assume text */
  261.         DELFLAG = DELDEFAULT;
  262.         LOGFLAG = LOGDEFAULT;
  263.         if (LOGFLAG) LOGFLAG = TRUE;
  264.            else LOGFLAG = FALSE;  /* set LOGFLAG to REALLY true or false */
  265.         ARPA = FALSE;  /* assume not on ARPA Net */
  266.         MUNGMODE = FALSE; /* protect files from overwriting */
  267.         NOMUNGMODE = TRUE; /* keep user from using MUNGMODE */
  268.         if ((strcmp(getlogin(),"zeus"))==0) NOMUNGMODE = FALSE;
  269.         STATDISP = FALSE;  /* assume not a status display */
  270.         BIT7 = FALSE;  /* assume 8-bit communication */
  271.         while ((flag = argv[1][index++]) != '\0')
  272.             switch (flag) {
  273.                 case '1' : FTP1 = TRUE;  /* select FTP 1 */
  274.                            delay = 5;  /* FTP 1 delay constant */
  275.                            printf("\nUMODEM:  TERM II FTP 1 Selected\n");
  276.                            break;
  277.                 case '4' : FTP1 = TRUE;  /* select FTP 1 (varient) */
  278.                            BIT7 = TRUE;  /* transfer only 7 bits */
  279.                            delay = 5;  /* FTP 1 delay constant */
  280.                            printf("\nUMODEM:  TERM II FTP 4 Selected\n");
  281.                            break;
  282.                 case '7' : BIT7 = TRUE;  /* transfer only 7 bits */
  283.                            break;
  284.                 case 'a' : ARPA = TRUE;  /* set ARPA Net */
  285.                            break;
  286.                 case 'c' : CMNDFLAG = TRUE;  /* command mode */
  287.                            break;
  288.                 case 'd' : DELFLAG = !DELDEFAULT;  /* delete log file ? */
  289.                            break;
  290.                 case 'l' : LOGFLAG = !LOGDEFAULT;  /* turn off log ? */
  291.                            break;
  292.                 case 'm' : 
  293.                            if(NOMUNGMODE) break;
  294.                            MUNGMODE = TRUE; /* allow overwriting of files */
  295.                            break;
  296.                 case 'o' : if ((i_port = open(getenv("MODEM"), 2)) > 0) 
  297.                                 o_port = i_port;
  298.                            else
  299.                                 i_port = 0;
  300.                            if (i_port) {
  301.                                printf("\nCommunications to %s\n", 
  302.                                    ttyname(i_port));
  303.                                CMNDFLAG = TRUE; /* turn on command mode */
  304.                                printf("Entering local mode\n");
  305.                            };
  306.                 break;
  307.  
  308.                 case 'p' : PMSG = TRUE;  /* print all messages */
  309.                            break;
  310.                 case 'r' : RECVFLAG = TRUE;  /* receive file */
  311.                            XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
  312.                            break;
  313.                 case 's' : SENDFLAG = TRUE;  /* send file */
  314.                            XMITTYPE = gettype(argv[1][index++]);
  315.                            break;
  316.                 case 'y' : STATDISP = TRUE;  /* display file status */
  317.                            break;
  318.                 default  : error("Invalid Flag", FALSE);
  319.                 }
  320.  
  321.         if (BIT7 && (XMITTYPE == 'b'))
  322.         {  printf("\nUMODEM:  Fatal Error -- Both 7-Bit Transfer and ");
  323.            printf("Binary Transfer Selected");
  324.            exit(-1);  /* error exit to UNIX */
  325.         }
  326.  
  327.         if (BIT7)  /* set MASK value */
  328.            BITMASK = 0177;  /* 7 significant bits */
  329.         else
  330.            BITMASK = 0377;  /* 8 significant bits */
  331.  
  332.         if (PMSG)
  333.            { printf("\nSupported File Transfer Protocols:");
  334.              printf("\n\tTERM II FTP 1");
  335.              printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
  336.              printf("\n\tTERM II FTP 4");
  337.              printf("\n\n");
  338.            }
  339.  
  340.         if (CMNDFLAG) LOGFLAG = TRUE;  /* if command mode, always log */
  341.         if (LOGFLAG)
  342.            { 
  343.              if ((fname = getenv("HOME")) == 0) /* Get HOME variable */
  344.                 error("Can't get Environment!", FALSE);
  345.              fname = strcat(fname, "/");
  346.              fname = strcat(fname, logfile);
  347.              if (!DELFLAG)
  348.                 LOGFP = fopen(fname, "a");  /* append to LOG file */
  349.              else
  350.                 LOGFP = fopen(fname, "w");  /* new LOG file */
  351.              if (!LOGFP)
  352.                 error("Can't Open Log File", FALSE);
  353.              fprintf(LOGFP,"\n\n++++++++\n");
  354.              fprintf(LOGFP,"\nUMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  355.              printf("\nUMODEM:  LOG File '%s' is Open\n", fname);
  356.            }
  357.  
  358.         if (STATDISP) {
  359.                 yfile(argv[2]);  /* status of a file */
  360.                 exit(0);  /* exit to UNIX */
  361.                 }
  362.  
  363.         if (RECVFLAG && SENDFLAG)
  364.                 error("Both Send and Receive Functions Specified", FALSE);
  365.         if (!RECVFLAG && !SENDFLAG && !CMNDFLAG)
  366.                 error("Send, Receive, or Command Functions NOT Given", FALSE);
  367.  
  368.         if (RECVFLAG)
  369.         {  if(open(argv[2], 0) != -1)  /* possible abort if file exists */
  370.            {    printf("\nUMODEM:  Warning -- Target File Exists\n");
  371.                 if( MUNGMODE == FALSE )
  372.                         error("Fatal - Can't overwrite file\n",FALSE);
  373.                 printf("UMODEM:  Overwriting Target File\n");
  374.            }
  375.            rfile(argv[2]);  /* receive file */
  376.         }
  377.         else {
  378.                 if (SENDFLAG) sfile(argv[2]);  /* send file */
  379.                 else command();  /* command mode */
  380.                 }
  381.         if (CMNDFLAG) LOGFLAG = TRUE;  /* for closing log file */
  382.         if (LOGFLAG) fclose(LOGFP);
  383.         exit(0);
  384. }
  385.  
  386. /*  Major Command Mode  */
  387. command()
  388. {
  389.         char cmd, *fname, *infile();
  390.         int command(), fpid, c;
  391.  
  392.         if (i_port) /* if local, then i_port is non-zero */
  393.                 signal(SIGINT, command);
  394.         printf("\nUMODEM Command Mode -- Type ? for Help");
  395.         do {
  396.            printf("\n");
  397.            printf(FTP1 ? "1" : "3");  /* FTP 1 or 3? */
  398.            printf(BIT7 ? "7" : " ");  /* BIT 7 or not? */
  399.            printf(ARPA ? "A" : " ");  /* ARPA Net or not? */
  400.            printf(LOGFLAG ? "L" : " ");  /* Log Entries or not? */
  401.            printf(MUNGMODE ? "M" : " ");  /* Mung Files or not? */
  402.            printf(" UMODEM> ");
  403.            scanf("%s", filename);
  404.            switch (cmd = mklow(filename[0])) {
  405.                 case 't' : if (!i_port) { /* only do it if local */
  406.                                 printf("Sorry, must be in local mode.\n");
  407.                                 break;
  408.                            }
  409.                            setmodes(1);
  410.                            /* setup raw and noecho for console */
  411.                            gtty(0, &ttycon);
  412.                            gtty(0, &ttycom);
  413.                            ttycom.sg_flags |= RAW;
  414.                            ttycom.sg_flags &= ~ECHO;
  415.                            stty(0, &ttycom);
  416.                            printf("\n\nEntering terminal mode\r\n\n");
  417.                            if (!(fpid = fork())) { 
  418.                                 /* child to read from modem */
  419.                                 signal(SIGINT, SIG_DFL);
  420.                                 do {
  421.                                     if ((c=readbyte(0)) > 0)
  422.                                         putchar(c);
  423.                                 } while(1);
  424.                            } else {
  425.                                 /* parent, reading from console */
  426.                                 while ((c=getchar()) != 'Q'-0x40)
  427.                                     sendbyte(c);
  428.                                 kill(fpid, 2);
  429.                            }
  430.                            /* put it back the way you got it */
  431.                catch=chmod(tty,00666);
  432.                            stty(0, &ttycon);
  433.                            printf("\n\nExiting terminal mode\n\n");
  434.                            break;
  435.                 case '1' : FTP1 = TRUE;  /* select FTP 1 */
  436.                            delay = 5;  /* FTP 1 delay constant */
  437.                            printf("\nTERM FTP 1 Selected");
  438.                            break;
  439.                 case '3' : FTP1 = FALSE; /* select FTP 3 */
  440.                            delay = 3;  /* FTP 3 delay constant */
  441.                            printf("\nTERM FTP 3 Selected");
  442.                            break;
  443.                 case '7' : BIT7 = ~BIT7;  /* toggle 7 bit transfer */
  444.                            printf("\n7-Bit Transfer %s Selected",
  445.                                 BIT7 ? "" : "NOT");
  446.                            break;
  447.                 case 'a' : ARPA = ~ARPA;  /* toggle ARPA Net */
  448.                            printf("\nDDN Interface %s Selected",
  449.                                 ARPA ? "" : "NOT");
  450.                            break;
  451.                 case 'l' : LOGFLAG = ~LOGFLAG;  /* toggle log flag */
  452.                            printf("\nEntry Logging %s Enabled",
  453.                                 LOGFLAG ? "" : "NOT");
  454.                            break;
  455.                 case 'm' : 
  456.                            if(NOMUNGMODE)
  457.                            {
  458.                            printf("\nOverwrite Permission Denied");
  459.                            break;
  460.                            }
  461.                            MUNGMODE = ~MUNGMODE; /* toggle file overwrite */
  462.                            printf("\nFile Overwriting %s Enabled",
  463.                                 MUNGMODE ? "" : "NOT");
  464.                            break;
  465.                 case 'r' : RECVFLAG = TRUE;  /* receive file */
  466.                            XMITTYPE = mklow(filename[1]);
  467.                            fname = infile();  /* get file name */
  468.                            if (*fname != '\0') 
  469.                               {  if(open(fname, 0) != -1)
  470.                                  {
  471.                           printf("\nUMODEM:  Warning -- Target File Exists\n");
  472.                                     if( MUNGMODE == FALSE )
  473.                                       {
  474.                                       printf("Fatal - Can't overwrite file\n");
  475.                                       break;
  476.                                       }
  477.                                   printf("UMODEM:  Overwriting Target File\n");
  478.                                   }
  479.                                  rfile(fname);
  480.                               }
  481.                            break;
  482.                 case 's' : SENDFLAG = TRUE;  /* send file */
  483.                            XMITTYPE = mklow(filename[1]);
  484.                            fname = infile();  /* get file name */
  485.                            if (*fname != '\0') sfile(fname);
  486.                            break;
  487.                 case 'x' : exit(0); /* hard core exit */
  488.                 case 'y' : fname = infile();  /* get file name */
  489.                            if (*fname != '\0') yfile(fname);
  490.                            break;
  491.                 default  : help(TRUE);
  492.            }
  493.         } while (cmd != 'x');
  494. }
  495.  
  496. /*  Get file name from user  */
  497. char *infile()
  498. {
  499.         char *startptr = filename;
  500.  
  501.         scanf("%s",startptr);
  502.         if (*startptr == '.') *startptr = '\0';  /* set NULL */
  503.         return(startptr);
  504. }
  505.  
  506. /*  Print Help Message  */
  507. help(caller)
  508. int caller;
  509. {
  510.         if (!caller) { printf("\nUsage:  \n\tumodem ");
  511.                 printf("-[o!c!rb!rt!sb!st][options]");
  512.                 printf(" filename\n");
  513.                 }
  514.         else {
  515.                 printf("\nUsage: r or s or option");
  516.                 }
  517.         printf("\nMajor Commands --");
  518.         if (!caller) printf("\n\tc  <-- Enter Command Mode");
  519.         printf("\n\to  <-- Operate in local mode");
  520.         printf("\n\trb <-- Receive Binary");
  521.         printf("\n\trt <-- Receive Text");
  522.         printf("\n\tsb <-- Send Binary");
  523.         printf("\n\tst <-- Send Text");
  524.         printf("\nOptions --");
  525.         printf("\n\t1  <-- (one) Employ TERM II FTP 1");
  526.         if (caller) printf("\n\t3  <-- Enable TERM FTP 3 (CP/M UG)");
  527.         if (!caller) printf("\n\t4  <-- Enable TERM FTP 4");
  528.         printf("\n\t7  <-- Enable 7-bit transfer mask");
  529.         printf("\n\ta  <-- Turn ON ARPA Net Flag");
  530.         if (!caller)
  531. #if DELDEFAULT == 1
  532.         printf("\n\td  <-- Do not delete umodem.log file before starting");
  533. #else
  534.         printf("\n\td  <-- Delete umodem.log file before starting");
  535. #endif
  536.  
  537.         if (!caller)
  538. #if LOGDEFAULT == 1
  539.         printf("\n\tl  <-- (ell) Turn OFF LOG File Entries");
  540. #else
  541.         printf("\n\tl  <-- (ell) Turn ON LOG File Entries");
  542. #endif
  543.         else printf("\n\tl  <-- Toggle LOG File Entries");
  544.  
  545.         printf("\n\tm  <-- Allow file overwiting on receive");
  546.         if (!caller) printf("\n\tp  <-- Turn ON Parameter Display");
  547.         if (caller) printf("\n\tx  <-- Exit");
  548.         printf("\n\ty  <-- Display file status (size) information only");
  549.         printf("\n");
  550. }
  551.  
  552. gettype(ichar)
  553. char ichar;
  554. {
  555.         if (ichar == 't') return(ichar);
  556.         if (ichar == 'b') return(ichar);
  557.         error("Invalid Send/Receive Parameter - not t or b", FALSE);
  558.         return;
  559. }
  560.  
  561. /* set tty modes for UMODEM transfers */
  562. setmodes()
  563. {
  564.  
  565.  
  566.         /* changed to get tty params from working console, so that
  567.            other mode changes would not interfere. */
  568.         if (gtty(0, &ttys) < 0)  /* get current tty params */
  569.                 error("Can't get TTY Parameters", TRUE);
  570.         tty = ttyname(i_port);  /* identify current tty */
  571.         /* transfer current modes to new structure */
  572.         if (!i_port) {
  573.                 ttysnew.sg_ispeed = ttys.sg_ispeed;     /* copy input speed */
  574.                 ttysnew.sg_ospeed = ttys.sg_ospeed;     /* copy output speed */
  575.         } else {
  576.                 ttysnew.sg_ispeed = B1200;
  577.                 ttysnew.sg_ospeed = B1200;
  578.         }
  579.         ttysnew.sg_erase  = ttys.sg_erase;      /* copy erase flags */
  580.         ttysnew.sg_flags  = ttys.sg_flags;      /* copy flags */
  581.         ttysnew.sg_kill   = ttys.sg_kill;       /* copy std terminal flags */
  582.         
  583.  
  584.         ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  585.                         /* This ORs in the RAW mode value, thereby
  586.                            setting RAW mode and leaving the other
  587.                            mode settings unchanged */
  588.         ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
  589.                         /* This ANDs in the complement of the ECHO
  590.                            setting (for NO echo), thereby leaving all
  591.                            current parameters unchanged and turning
  592.                            OFF ECHO only */
  593.         ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
  594.         ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
  595.         ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
  596.         ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
  597.         ttysnew.sg_flags &= ~TAB0; /* turn off tab delays */
  598.         ttysnew.sg_flags &= ~TAB1;
  599.         ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
  600.         ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
  601.         ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
  602.  
  603.         if (stty(i_port, &ttysnew) < 0)  /* set new params */
  604.                 error("Can't set new TTY Parameters", TRUE);
  605.  
  606.         if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  607.                 error("Can't get your TTY Status", TRUE);
  608.         if (statbuf.st_mode & 022)      /* Need to turn messages off */
  609.                 if (chmod(tty, statbuf.st_mode & ~022) < 0)
  610.                         error("Can't change  TTY mode", TRUE);
  611.                 else wason = TRUE;
  612.         else wason = FALSE;
  613.  
  614.         if (PMSG)
  615.                 { printf("\nUMODEM:  TTY Device Parameters Altered");
  616.                   ttyparams();  /* print tty params */
  617.                 }
  618.  
  619.         if (ARPA)  /* set 8-bit on ARPA Net */
  620.                 setarpa();
  621.  
  622.         return;
  623. }
  624.  
  625. /*  set ARPA Net for 8-bit transfers  */
  626. setarpa()
  627. {
  628.         sendbyte(IAC);  /* Is A Command */
  629.         sendbyte(WILL); /* Command to SERVER TELNET (Host) */
  630.         sendbyte(TRBIN);        /* Command is:  Transmit Binary */
  631.  
  632.         sendbyte(IAC);  /* Is A Command */
  633.         sendbyte(DO);   /* Command to TIP */
  634.         sendbyte(TRBIN);        /* Command is:  Transmit Binary */
  635.  
  636.         sleep(3);  /* wait for TIP to configure */
  637.  
  638.         return;
  639. }
  640.  
  641. /* restore normal tty modes */
  642. restoremodes(errcall)
  643. int errcall;
  644. {
  645.         if (ARPA)  /* if ARPA Net, reconfigure */
  646.                 resetarpa();
  647.  
  648.         if (wason)
  649.                 if (chmod(tty, statbuf.st_mode | 022) < 0)
  650.                         error("Can't change TTY mode", FALSE);
  651.  
  652.         if (stty(i_port, &ttys) < 0)  /* restore original tty modes */
  653.                 { if (!errcall)
  654.                    error("RESET - Can't restore normal TTY Params", FALSE);
  655.                 else
  656.                    { printf("UMODEM:  ");
  657.                      printf("RESET - Can't restore normal TTY Params\n");
  658.                    }
  659.                 }
  660.  
  661.         if (PMSG)
  662.                 { printf("\nUMODEM:  TTY Device Parameters Restored");
  663.                   ttyparams();  /* print tty params */
  664.                 }
  665.  
  666.         return;
  667. }
  668.  
  669. /* reset the ARPA Net */
  670. resetarpa()
  671. {
  672.         sendbyte(IAC);  /* Is A Command */
  673.         sendbyte(WONT); /* Negative Command to SERVER TELNET (Host) */
  674.         sendbyte(TRBIN);        /* Command is:  Don't Transmit Binary */
  675.  
  676.         sendbyte(IAC);  /* Is A Command */
  677.         sendbyte(DONT); /* Negative Command to TIP */
  678.         sendbyte(TRBIN);        /* Command is:  Don't Transmit Binary */
  679.  
  680.         return;
  681. }
  682.  
  683. /* print error message and exit; if mode == TRUE, restore normal tty modes */
  684. error(msg, mode)
  685. char *msg;
  686. int mode;
  687. {
  688.         if (mode)
  689.                 restoremodes(TRUE);  /* put back normal tty modes */
  690.         printf("UMODEM:  %s\n", msg);
  691.         if (LOGFLAG & (int)LOGFP)
  692.         {   fprintf(LOGFP, "UMODEM Fatal Error:  %s\n", msg);
  693.             fclose(LOGFP);
  694.         }
  695.         exit(-1);
  696. }
  697.  
  698. /**  print status (size) of a file  **/
  699. yfile(name)
  700. char *name;
  701. {
  702.         printf("\nUMODEM File Status Display for %s\n", name);
  703.  
  704.         if (open(name,0) < 0) {
  705.                 printf("File %s does not exist\n", name);
  706.                 return;
  707.                 }
  708.  
  709.         prfilestat(name);  /* print status */
  710.         printf("\n");
  711. }
  712.  
  713. getbyte(fildes, ch)                             /* Buffered disk read */
  714. int fildes;
  715. char *ch;
  716. /*
  717.  *
  718.  *      Get a byte from the specified file.  Buffer the read so we don't
  719.  *      have to use a system call for each character.
  720.  *
  721.  */
  722.  
  723. {
  724.         static char buf[BUFSIZ];        /* Remember buffer */
  725.         static char *bufp = buf;        /* Remember where we are in buffer */
  726.         
  727.         if (nbchr == 0)                 /* Buffer exausted; read some more */
  728.         {
  729.                 if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  730.                         error("File Read Error", TRUE);
  731.                 bufp = buf;             /* Set pointer to start of array */
  732.         }
  733.         if (--nbchr >= 0)
  734.         {
  735.                 *ch = *bufp++;
  736.                 return(0);
  737.         }
  738.         else
  739.                 return(EOF);
  740. }
  741.  
  742. /**  receive a file  **/
  743. rfile(name)
  744. char *name;
  745. {
  746.         char mode;
  747.         int fd, j, firstchar, sectnum, sectcurr, tmode;
  748.         int sectcomp, errors, errorflag, recfin;
  749.         register int bufctr, checksum;
  750.         register int c;
  751.         int errorchar, fatalerror, startstx, inchecksum, endetx, endenq;
  752.         long recvsectcnt;
  753.  
  754.         mode = XMITTYPE;  /* set t/b mode */
  755.         if ((fd = creat(name, CREATMODE)) < 0)
  756.                 error("Can't create file for receive", FALSE);
  757.         setmodes();  /* setup tty modes for xfer */
  758.         printf("\r\nUMODEM:  File Name: %s", name);
  759.         if (LOGFLAG)
  760.         {    fprintf(LOGFP, "\n----\nUMODEM Receive Function\n");
  761.              fprintf(LOGFP, "File Name: %s\n", name);
  762.              if (FTP1)
  763.                 if (!BIT7)
  764.                  fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  765.                 else
  766.                  fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  767.              else
  768.                 fprintf(LOGFP,
  769.                   "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  770.              if (BIT7)
  771.                 fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  772.              else
  773.                 fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  774.         }
  775.         printf("\r\nUMODEM:  ");
  776.         if (BIT7)
  777.                 printf("7-Bit");
  778.         else
  779.                 printf("8-Bit");
  780.         printf(" Transmission Enabled");
  781.         printf("\r\nUMODEM:  Ready to RECEIVE File\r\n");
  782.  
  783.         recfin = FALSE;
  784.         sectnum = errors = 0;
  785.         fatalerror = FALSE;  /* NO fatal errors */
  786.         recvsectcnt = 0;  /* number of received sectors */
  787.  
  788.         if (mode == 't')
  789.                 tmode = TRUE;
  790.         else
  791.                 tmode = FALSE;
  792.  
  793.         if (tmode && i_port)
  794.                 printf("\n\rText mode conversions activated (cp/m files)\n\r");
  795.  
  796.         if (i_port)
  797.                 printf("\nSync...\n\n");
  798.         if (FTP1)
  799.         {
  800.           while (readbyte(4) != SYN);
  801.           sendbyte(ACK);  /* FTP 1 Sync */
  802.         }
  803.         else sendbyte(NAK);  /* FTP 3 Sync */
  804.  
  805.         do
  806.         {   errorflag = FALSE;
  807.             do {
  808.                   firstchar = readbyte(6);
  809.             } while ((firstchar != SOH) && (firstchar != EOT) && (firstchar 
  810.                      != TIMEOUT));
  811.             if (firstchar == TIMEOUT)
  812.             {  if (LOGFLAG)
  813.                 fprintf(LOGFP, "Timeout on Sector %d\n", sectnum);
  814.                errorflag = TRUE;
  815.             }
  816.  
  817.             if (firstchar == SOH)
  818.             {  if (FTP1) readbyte(5);  /* discard leading zero */
  819.                sectcurr = readbyte(delay);
  820.                sectcomp = readbyte(delay);
  821.                if (FTP1) startstx = readbyte(delay);  /* get leading STX */
  822.                if ((sectcurr + sectcomp) == BITMASK)
  823.                {  if (sectcurr == ((sectnum+1)&BITMASK))
  824.                   {  checksum = 0;
  825.                      for (j = bufctr = 0; j < BBUFSIZ; j++)
  826.                      {  buff[bufctr] = c = readbyte(delay);
  827.                         checksum = ((checksum+c)&BITMASK);
  828.                         if (!tmode)  /* binary mode */
  829.                         {  bufctr++;
  830.                            continue;
  831.                         }
  832.                         if (c == CR)
  833.                            continue;  /* skip CR's */
  834.                         if (c == CTRLZ)  /* skip CP/M EOF char */
  835.                         {  recfin = TRUE;  /* flag EOF */
  836.                            continue;
  837.                         }
  838.                         if (!recfin)
  839.                            bufctr++;
  840.                      }
  841.                      if (FTP1) endetx = readbyte(delay);  /* get ending ETX */
  842.                      inchecksum = readbyte(delay);  /* get checksum */
  843.                      if (FTP1) endenq = readbyte(delay); /* get ENQ */
  844.                      if (checksum == inchecksum)  /* good checksum */
  845.                      {  errors = 0;
  846.                         recvsectcnt++;
  847.                         sectnum = sectcurr;  /* update sector counter */
  848.                         if (write(fd, buff, bufctr) < 0)
  849.                            error("File Write Error", TRUE);
  850.                         else
  851.                         {  
  852.                            if (i_port)
  853.                                 printf("Received Sector %d\r", sectcurr);
  854.                             if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  855.                            sendbyte(ACK);
  856.                         }
  857.                      }
  858.                      else
  859.                      {  if (LOGFLAG)
  860.                                 fprintf(LOGFP, "Checksum Error on Sector %d\n",
  861.                                 sectnum);
  862.                         errorflag = TRUE;
  863.                      }
  864.                   }
  865.                   else
  866.                   { if (sectcurr == sectnum)
  867.                     {  while(readbyte(3) != TIMEOUT);
  868.                        if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  869.                        sendbyte(ACK);
  870.                     }
  871.                     else
  872.                     {  if (LOGFLAG)
  873.                         { fprintf(LOGFP, "Phase Error - Received Sector is ");
  874.                           fprintf(LOGFP, "%d while Expected Sector is %d\n",
  875.                            sectcurr, ((sectnum+1)&BITMASK));
  876.                         }
  877.                         errorflag = TRUE;
  878.                         fatalerror = TRUE;
  879.                         if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  880.                         sendbyte(CAN);
  881.                     }
  882.                   }
  883.            }
  884.            else
  885.            {  if (LOGFLAG)
  886.                 fprintf(LOGFP, "Header Sector Number Error on Sector %d\n",
  887.                    sectnum);
  888.                errorflag = TRUE;
  889.            }
  890.         }
  891.         if (FTP1 && !errorflag)
  892.         {  if (startstx != STX)
  893.            {  errorflag = TRUE;  /* FTP 1 STX missing */
  894.               errorchar = STX;
  895.            }
  896.            if (endetx != ETX)
  897.            {  errorflag = TRUE;  /* FTP 1 ETX missing */
  898.               errorchar = ETX;
  899.            }
  900.            if (endenq != ENQ)
  901.            {  errorflag = TRUE;  /* FTP 1 ENQ missing */
  902.               errorchar = ENQ;
  903.            }
  904.            if (errorflag && LOGFLAG)
  905.            {  fprintf(LOGFP, "Invalid Packet-Control Character:  ");
  906.               switch (errorchar) {
  907.                 case STX : fprintf(LOGFP, "STX"); break;
  908.                 case ETX : fprintf(LOGFP, "ETX"); break;
  909.                 case ENQ : fprintf(LOGFP, "ENQ"); break;
  910.                 default  : fprintf(LOGFP, "Error"); break;
  911.               }
  912.               fprintf(LOGFP, "\n");
  913.            }
  914.         }
  915.         if (errorflag == TRUE)
  916.         {  errors++;
  917.            while (readbyte(3) != TIMEOUT);
  918.            sendbyte(NAK);
  919.         }
  920.   }
  921.   while ((firstchar != EOT) && (errors != ERRORMAX) && !fatalerror);
  922.   if ((firstchar == EOT) && (errors < ERRORMAX))
  923.   {  if (!FTP1) sendbyte(ACK);
  924.      close(fd);
  925.      restoremodes(FALSE);  /* restore normal tty modes */
  926.      if (FTP1)
  927.         while (readbyte(3) != TIMEOUT);  /* flush EOT's */
  928.      sleep(3);  /* give other side time to return to terminal mode */
  929.      if (LOGFLAG)
  930.      {  fprintf(LOGFP, "\nReceive Complete\n");
  931.         fprintf(LOGFP,"Number of Received CP/M Records is %ld\n", recvsectcnt);
  932.      }
  933.      printf("\n");
  934.   }
  935.   else
  936.   {  if (LOGFLAG && FTP1 && fatalerror) fprintf(LOGFP,
  937.         "Synchronization Error");
  938.      error("TIMEOUT -- Too Many Errors", TRUE);
  939.   }
  940. }
  941.  
  942. /**  send a file  **/
  943. sfile(name)
  944. char *name;
  945. {
  946.         char mode, c;
  947.         int fd, attempts, nlflag, sendfin, tmode, sendresp;
  948.         register int bufctr, checksum, sectnum;
  949.  
  950.         nbchr = 0;  /* clear buffered read char count */
  951.         mode = XMITTYPE;  /* set t/b mode */
  952.         if ((fd = open(name, 0)) < 0)
  953.         {  if (LOGFLAG) fprintf(LOGFP, "Can't Open File\n");
  954.            error("Can't open file for send", FALSE);
  955.         }
  956.         setmodes();  /* setup tty modes for xfer */     
  957.         printf("\r\nUMODEM:  File Name: %s", name);
  958.         if (LOGFLAG)
  959.         {   fprintf(LOGFP, "\n----\nUMODEM Send Function\n");
  960.             fprintf(LOGFP, "File Name: %s\n", name);
  961.         }
  962.         printf("\r\n"); prfilestat(name);  /* print file size statistics */
  963.         if (LOGFLAG)
  964.         {  if (FTP1)
  965.               if (!BIT7)
  966.                 fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  967.               else
  968.                 fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  969.            else
  970.                 fprintf(LOGFP,
  971.                    "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  972.            if (BIT7)
  973.                 fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  974.            else
  975.                 fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  976.         }
  977.         printf("\r\nUMODEM:  ");
  978.         if (BIT7)
  979.                 printf("7-Bit");
  980.         else
  981.                 printf("8-Bit");
  982.         printf(" Transmission Enabled");
  983.         printf("\r\nUMODEM:  Ready to SEND File\r\n");
  984.  
  985.         if (mode == 't')
  986.            tmode = TRUE;
  987.         else
  988.            tmode = FALSE;
  989.  
  990.         if (tmode && i_port)
  991.                 printf("\n\rText mode conversions activated (cp/m files)\n\r");
  992.         sendfin = nlflag = FALSE;
  993.         attempts = 0;
  994.  
  995.         if (i_port)
  996.                 printf("\nSync...\n\n");
  997.         if (FTP1)
  998.         {  sendbyte(SYN);  /* FTP 1 Synchronize with Receiver */
  999.            while (readbyte(5) != ACK)
  1000.            {  if(++attempts > RETRYMAX*6) error("Remote System Not Responding",
  1001.                 TRUE);
  1002.               sendbyte(SYN);
  1003.            }
  1004.         }
  1005.         else
  1006.         {  while (readbyte(30) != NAK)  /* FTP 3 Synchronize with Receiver */
  1007.            if (++attempts > RETRYMAX) error("Remote System Not Responding",
  1008.                 TRUE);
  1009.         }
  1010.  
  1011.         sectnum = 1;  /* first sector number */
  1012.         attempts = 0;
  1013.  
  1014.         do 
  1015.         {   for (bufctr=0; bufctr < BBUFSIZ;)
  1016.             {   if (nlflag)
  1017.                 {  buff[bufctr++] = LF;  /* leftover newline */
  1018.                    nlflag = FALSE;
  1019.                 }
  1020.                 if (getbyte(fd, &c) == EOF)
  1021.                 {  sendfin = TRUE;  /* this is the last sector */
  1022.                    if (!bufctr)  /* if EOF on sector boundary */
  1023.                       break;  /* avoid sending extra sector */
  1024.                    if (tmode)
  1025.                       buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
  1026.                    else
  1027.                       bufctr++;
  1028.                    continue;
  1029.                 }
  1030.                 if (tmode && c == LF)  /* text mode & Unix newline? */
  1031.                 {  if (c == LF)  /* Unix newline? */
  1032.                    {  buff[bufctr++] = CR;  /* insert carriage return */
  1033.                       if (bufctr < BBUFSIZ)
  1034.                          buff[bufctr++] = LF;  /* insert Unix newline */
  1035.                       else
  1036.                          nlflag = TRUE;  /* insert newline on next sector */
  1037.                    }
  1038.                    continue;
  1039.                 }       
  1040.                 buff[bufctr++] = c;  /* copy the char without change */
  1041.             }
  1042.             attempts = 0;
  1043.         
  1044.             if (!bufctr)  /* if EOF on sector boundary */
  1045.                break;  /* avoid sending empty sector */
  1046.  
  1047.             do
  1048.             {   
  1049.                 if (i_port)
  1050.                         printf("Sending Sector %d\r", sectnum);
  1051.                 sendbyte(SOH);  /* send start of packet header */
  1052.                 if (FTP1) sendbyte(0);  /* FTP 1 Type 0 Packet */
  1053.                 sendbyte(sectnum);  /* send current sector number */
  1054.                 sendbyte(-sectnum-1);  /* and its complement */
  1055.                 if (FTP1) sendbyte(STX);  /* send STX */
  1056.                 checksum = 0;  /* init checksum */
  1057.                 for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
  1058.                 {  sendbyte(buff[bufctr]);  /* send the byte */
  1059.                    if (ARPA && (buff[bufctr]==0xff))  /* ARPA Net FFH esc */
  1060.                         sendbyte(buff[bufctr]);  /* send 2 FFH's for one */
  1061.                    checksum = ((checksum+buff[bufctr])&BITMASK);
  1062.                 }
  1063. /*              while (readbyte(3) != TIMEOUT);   flush chars from line */
  1064.                 if (FTP1) sendbyte(ETX);  /* send ETX */
  1065.                 sendbyte(checksum);  /* send the checksum */
  1066.                 if (FTP1) sendbyte(ENQ);  /* send ENQ */
  1067.                 attempts++;
  1068.                 if (FTP1)
  1069.                 {  sendresp = NAK;  /* prepare for NAK */
  1070.                    if (readbyte(10) == ESC) sendresp = readbyte(10);
  1071.                 }
  1072.                 else
  1073.                    sendresp = readbyte(10);  /* get response */
  1074.                 if ((sendresp != ACK) && LOGFLAG)
  1075.                    { fprintf(LOGFP, "Non-ACK Received on Sector %d\n",
  1076.                       sectnum);
  1077.                      if (sendresp == TIMEOUT)
  1078.                         fprintf(LOGFP, "This Non-ACK was a TIMEOUT\n");
  1079.                    }
  1080.             }   while((sendresp != ACK) && (attempts != RETRYMAX));
  1081.             sectnum++;  /* increment to next sector number */
  1082.     }  while (!sendfin && (attempts != RETRYMAX));
  1083.  
  1084.     if (attempts == RETRYMAX)
  1085.         error("Remote System Not Responding", TRUE);
  1086.  
  1087.     attempts = 0;
  1088.     if (FTP1)
  1089.         while (attempts++ < 10) sendbyte(EOT);
  1090.     else
  1091.     {   sendbyte(EOT);  /* send 1st EOT */
  1092.         while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
  1093.            sendbyte(EOT);
  1094.         if (attempts >= RETRYMAX)
  1095.            error("Remote System Not Responding on Completion", TRUE);
  1096.     }
  1097.  
  1098.     close(fd);
  1099.     restoremodes(FALSE);  
  1100.     sleep(5);  /* give other side time to return to terminal mode */
  1101.     if (LOGFLAG)
  1102.     {  fprintf(LOGFP, "\nSend Complete\n");
  1103.     }
  1104.     printf("\n");
  1105.  
  1106. }
  1107.  
  1108. /*  print file size status information  */
  1109. prfilestat(name)
  1110. char *name;
  1111. {
  1112.         struct stat filestatbuf; /* file status info */
  1113.  
  1114.         stat(name, &filestatbuf);  /* get file status bytes */
  1115.         printf("  Estimated File Size %ldK, %ld Records, %ld Bytes",
  1116.           (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  1117.           filestatbuf.st_size);
  1118.         if (LOGFLAG)
  1119.           fprintf(LOGFP,"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
  1120.           (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  1121.           filestatbuf.st_size);
  1122.         return;
  1123. }
  1124.  
  1125. /* get a byte from data stream -- timeout if "seconds" elapses */
  1126. readbyte(seconds)
  1127. unsigned seconds;
  1128. {
  1129.         char c;
  1130.         
  1131.         signal(SIGALRM,alarmfunc);  /* catch alarms */  
  1132.         alarm(seconds);  /* set the alarm clock */
  1133.         if (read(i_port, &c, 1) < 0)  /* get a char; error means we timed out */
  1134.           {
  1135.              return(TIMEOUT);
  1136.           }
  1137.         alarm(0);  /* turn off the alarm */
  1138.         return((c&BITMASK));  /* return the char */
  1139. }
  1140.  
  1141. /* send a byte to data stream */
  1142. sendbyte(data)
  1143. char data;
  1144. {
  1145.         char dataout;
  1146.         dataout = (data&BITMASK);  /* mask for 7 or 8 bits */
  1147.         write(o_port, &dataout, 1);  /* write the byte */
  1148.         return;
  1149. }
  1150.  
  1151. /* function for alarm clock timeouts */
  1152. alarmfunc()
  1153. {
  1154.         return;  /* this is basically a dummy function to force error */
  1155.                  /* status return on the "read" call in "readbyte"    */
  1156. }
  1157.  
  1158. /* print data on TTY setting */
  1159. ttyparams()
  1160. {
  1161.         
  1162.         gtty(i_port, &ttystemp);  /* get current tty params */
  1163.  
  1164.         tty = ttyname(i_port);  /* get name of tty */
  1165.         stat(tty, &statbuf);  /* get more tty params */
  1166.  
  1167.         printf("\r\n\nTTY Device Parameter Display");
  1168.           printf("\r\n\tTTY Device Name is %s\r\n\n", tty);
  1169.           printf("\tAny Parity Allowed "); pryn(ANYP);
  1170.           printf("\tEven Parity Allowed"); pryn(EVENP);
  1171.           printf("\tOdd Parity Allowed "); pryn(ODDP);
  1172.           printf("\tEcho Enabled       "); pryn(ECHO);
  1173.           printf("\tLower Case Map     "); pryn(LCASE);
  1174.           printf("\tTabs Expanded      "); pryn(XTABS);
  1175.           printf("\tCR Mode Enabled    "); pryn(CRMOD);
  1176.           printf("\tRAW Mode Enabled   "); pryn(RAW);
  1177.  
  1178.           printf("\tTTY Input Rate     :   ");
  1179.             prbaud(ttystemp.sg_ispeed);
  1180.           printf("\tTTY Output Rate    :   ");
  1181.             prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
  1182. }
  1183.  
  1184. pryn(iflag)
  1185. int iflag;
  1186. {
  1187.  
  1188.         if (ttystemp.sg_flags&iflag)
  1189.  
  1190.            printf(":   Yes\r\n");
  1191.         else
  1192.            printf(":   No\r\n");
  1193. }
  1194.  
  1195.  
  1196. prbaud(speed)
  1197. char speed;
  1198. {
  1199.         switch (speed) {
  1200.  
  1201.                 case B75 : printf("75"); break;
  1202.                 case B110 : printf("110"); break;
  1203.                 case B134 : printf("134.5"); break;
  1204.                 case B150 : printf("150"); break;
  1205.                 case B200 : printf("200"); break;
  1206.                 case B300 : printf("300"); break;
  1207.                 case B600 : printf("600"); break;
  1208.                 case B1200 : printf("1200"); break;
  1209.                 case B1800 : printf("1800"); break;
  1210.                 case B2400 : printf("2400"); break;
  1211.                 case B4800 : printf("4800"); break;
  1212.                 case B9600 : printf("9600"); break;
  1213.                 default : printf("Error");break;
  1214.  
  1215.         }
  1216.         printf(" Baud\r\n");
  1217.  
  1218. }
  1219.  
  1220.